#include "stdafx.h"
#include "../arch/pe/arhcpe.h"

namespace xm
{
	class GenericArchive : public IKArchive, UnkBase
	{
	protected:
		iptr<IKFileStream>	_file;
		FMTID				_fmtid;
	public:
		UNKNOWN_IMP1(IKArchive);
		DEFAULT_INIT_CLASS();
		GenericArchive(): _fmtid(FMT_NONE){}
		STDMETHOD(Open)( IUnknown * pstm, FMTID fmt, SIZE_T flags )
		{
			Close();
			if( !pstm ) return E_INVALIDARG;
			_file = pstm;
			if( !_file ) return E_NOINTERFACE;
			_fmtid = fmt;
			return S_OK;
		}
		STDMETHOD(ReOpen)( SIZE_T flags )
		{
			return S_OK;
		}
		STDMETHOD(Close)() 
		{
			_fmtid = FMT_NONE;
			_file.dispose();
			return S_OK;
		}
		STDMETHOD(GetStream)( IKFileStream** pstm )
		{
			if( !_file ) return E_UNEXPECTED;
			if( !pstm ) return E_INVALIDARG;
			*pstm = _file;
			_file->AddRef();
			return S_OK;
		}
		STDMETHOD(GetFormat)( UINT32 * lpFormatId )
		{
			if( !lpFormatId ) return E_INVALIDARG;
			*lpFormatId = _fmtid;
			return S_OK;
		}
	};

	struct ARCHIVE_DESC
	{
		FMTID					FmtId;
		TGetClassObject			Gettor;
	};

#define		DEFINE_FORMAT(x, cls)			{ FMT_##x, TStdClsFactory<cls>::GetClassObject }

	static ARCHIVE_DESC Formats[] = 
	{
		DEFINE_FORMAT( NONE,	GenericArchive	),
		DEFINE_FORMAT( PE,		WinPeParser	),
		DEFINE_FORMAT( SWX,		GenericArchive	),
		DEFINE_FORMAT( PDF,		GenericArchive	),
		DEFINE_FORMAT( DOC,		GenericArchive	),
		DEFINE_FORMAT( RTF,		GenericArchive	),
		DEFINE_FORMAT( DEX,		GenericArchive	),
		DEFINE_FORMAT( JCLS,	GenericArchive	),
	};

	CONST SIZE_T NUM_OF_FORMATS = sizeof(Formats)/sizeof(Formats[0]);

	HRESULT XmCreateArchive( FMTID fmt, IUnknown* outer, REFIID riid, void** ppv, IUnknown* xt )
	{
		for( SIZE_T i = 0; i < NUM_OF_FORMATS; ++ i )
		{
			if( Formats[i].FmtId != fmt ) continue;
			iptr<IKClassFactory> fact;
			RFAILED( Formats[i].Gettor( face_id(IKClassFactory), fact.vpp() ) );
			return fact->CreateInstance( xt, outer, riid, ppv );
		}
		return E_NOTIMPL;
	}

};
